const defAttr = () => ({
  data: {}, //drawArrays
  // 'a_Position': {
  //     size: 2, 必须
  //     array: [], 必须
  //     buffer: null,
  //     location: a_Position,
  //     needUpdate: true //是否需要更新
  // }
  element: null, //drawElements
  //{
  //     array:[], 必须
  //     buffer: null,
  //     needUpdate: true //是否需要更新
  //}
  count: 0, //顶点数量 用于渲染是使用
  drawType: "drawArrays", //渲染方法
});

//集合体对象
//只存储Attrib类型的对象
export default class Geo {
  constructor(attr) {
    Object.assign(this, defAttr(), attr);
  }

  init(gl) {
    this._initData(gl);
    this._initIndex(gl);
    this._updateDrawCount();
  }

  //初始化顶点信息
  _initData(gl) {
    Object.entries(this.data).forEach(([key, value], index) => {
      let buffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
      gl.bufferData(gl.ARRAY_BUFFER, value.array, gl.STATIC_DRAW);
      gl.bindBuffer(gl.ARRAY_BUFFER, null);
      value.buffer = buffer;
      value.needUpdate = true;
    });
  }

  //初始化顶点索引
  _initIndex(gl) {
    const { element } = this;
    if (element) {
      let buffer = gl.createBuffer();
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, element.array, gl.STATIC_DRAW);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
      element.buffer = buffer;
      element.needUpdate = true;
    }
  }

  _updateDrawCount() {
    const { element } = this;
    if (element) {
      this.count = element.array.length;
      this.drawType = "drawElements";
    } else {
      const { array, size } = this.data["a_Position"];
      this.count = array.length / size;
      this.drawType = "drawArrays";
    }
  }

  update(gl, attribs) {
    this._updateData(gl, attribs);
    this._updataIndex(gl);
  }

  //attribs是Map对象
  _updateData(gl, attribs) {
    Object.entries(this.data).forEach(([key, value], index) => {
      const { size, buffer, array } = value;
      const location = attribs.get(key);
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
      if (value.needUpdate) {
        gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
        gl.vertexAttribPointer(location, value.size, gl.FLOAT, false, 0, 0); //因为只传入顶点数据点数据,所以后两位可以直接填0
        gl.enableVertexAttribArray(location);
        value.needUpdate = false;

        if (key == "a_Position") {
          this._updateDrawCount();
        }
      }
      gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
    });
  }

  _updataIndex(gl) {
    const { element } = this;
    if (element) {
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, element.buffer);
      if (element.needUpdate) {
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, element.array, gl.STATIC_DRAW);
        element.needUpdate = false;
      }
    }
  }

  setData(key, value) {
    const { data } = this;
    if (!data[key]) {
      console.log("data null");
      return;
    }
    data[key].needUpdate = true;
    Object.assign(data[key], value);
  }

  setElement(value) {
    if (value) {
      if (this.element == null) {
        this.element = {};
      }
      const { element } = this;
      this.count = value.length;
      element.array = value;
      element.needUpdate = true;
      this.drawType = "drawElements";
    } else {
      const { array, size } = this.data["a_Position"];
      this.count = array.length / size;
      this.drawType = "drawArrays";
    }
  }

  clone() {
    const { data, element } = this;

    let curData = {};
    Object.entries(data).forEach(([key, val], index) => {
      curData[key] = {
        size: val.size,
        array: new Float32Array(val.array),
      };
    });

    let curElement = {
      array: new Uint8Array(element.array),
    };

    return new Geo({
      data: curData,
      element: curElement,
    });
  }
}
